import pandas as pd
import numpy as np
import logging
import tensorflow as tf
import os
import re

# 配置日志级别和基本设置
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    filename='app.log',
                    filemode='a')

__Cannel_TASK_WAIT_HANDLE__ = False

def Channel():
    __Cannel_TASK_WAIT_HANDLE__ = True

def binary_strings_to_integers(binary_strings):
    # 将所有输入的二进制字符串转换为整数的列表
    result = []
    # 如果字符串长度不是8的倍数，在前面补零
    if len(binary_strings) % 8 != 0:
        binary_strings = binary_strings + '0'
    # 按照每8个字符分组
    chunks = [binary_strings[i:i+8] for i in range(0, len(binary_strings), 8)]
    
    # 将每个8位的二进制字符串转换为整数
    integers = [int(chunk, 2) for chunk in chunks]
    result.extend(integers)
    return result

def lstm_process_target_data(data_pain, L=10):
    '''
    L:数据截断或填充后的长度，程序默认为10

    '''
    X_test = np.vstack(data_pain)
    X_test = X_test / 255

    X_test = np.reshape(X_test, [-1, L, 1])

    return X_test


def binary_df_to_mingmi(df, L):
    # 创建两个列表来保存明文和密文数据
    all_list = []
    # 遍历每一行的数据
    for _, row in df.iterrows():
        if __Cannel_TASK_WAIT_HANDLE__ == False:
            data = row['data']
            # 将二进制字符串转换为整数
            byte_str = binary_strings_to_integers(data)
            if len(byte_str) > L:
                byte_str = byte_str[:L]
            elif len(byte_str) < L:
                byte_str += [0] * (L - len(byte_str))  # 用0填充

            all_list.append(byte_str)
        else:
            raise "用户已取消当前操作"
    print('数据加载成功')
    logging.info('数据加载成功')
    return np.array(all_list)

def lstm_TL(X_test, file_name):

    batch_size = 64
    model = tf.keras.models.load_model(file_name)

    # 测试集上的批次预测和性能评估
    # 初始化预测结果列表
    res_ypred = []
    test_accs = []

    # 遍历测试数据集
    for batch_xs in tf.data.Dataset.from_tensor_slices(X_test).batch(batch_size):
        if __Cannel_TASK_WAIT_HANDLE__ == False:
            batch_preds = model.predict(batch_xs)
            batch_ypred = tf.argmax(batch_preds, axis=1).numpy()
            res_ypred.extend(batch_ypred)

        else:
            raise ValueError("用户已取消当前操作")

    # 保存预测结果
    # temp = np.arange(1, len(res_ypred) + 1, 1)
    res_ypred = np.array(res_ypred)  # 将列表转换为NumPy数组
    # res_out = np.hstack((temp.reshape(-1, 1), res_ypred.reshape(-1, 1)))

    print('预测结束')
    logging.info('预测结束')

    return res_ypred

def main(parameters):
    waibu_data_1 = parameters['waibu_data_1']
    model_path = parameters['model_path']

    model_name = os.path.basename(model_path)
    pattern = r'model_(\d+)B\.h5'
    match = re.search(pattern, model_name)
    if match:
        jieduan = int(match.group(1))
    else:
        raise ValueError('模型选择错误')

    data = pd.read_csv(waibu_data_1)
    all_test = binary_df_to_mingmi(data, jieduan)
    data_test = lstm_process_target_data(all_test, jieduan)

    pred = lstm_TL(data_test, model_path)

    output = (((pd.concat(
        [pd.DataFrame(data['data'], columns=['data']),
         pd.DataFrame(pred, columns=['predict label'])], axis=1))))

    result_dict = {
        'output': output
    }
    return result_dict

if __name__ == '__main__':
    parameters1 = {
        'waibu_data_1': r'D:\temp\xinda\mingmi\dataset\外部数据_分类002.csv',
        'model_path': r'D:\temp\xinda\mingmi\dataset\模型\model_20B.h5'    # 完整模型地址
    }
    result_dict = main(parameters1)
